﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.WebPartPages;

namespace CSI
{
	/// <summary>
	/// This SharePoint 2010 web part is designed to provide a rolling dropdown list of dates 
	/// shown in 'month year' format (e.g. Mar 2011). The values (dates) listed in the list
	/// are dynamic so that they change with the current date. The custom property settings
	/// for the web part allow the user to specify how many months offset from the current date
	/// should the list of months begin and how many months should be displayed in the list.
	/// And example would be if the current date is Mar 2011 and the start offset date is 3 
	/// months, then the first month displayed in the dropdown would be Jun 2011 (3 months 
	/// from the current date). Then, additional month entries would be added descending 
	/// from Jun 2011.
	/// 
	/// The custom properties allow the user to set the offset start date as described above, 
	/// as well as the offset default date which is the first month/year shown to the user.
	/// The start offset date may be 3 months to the future, while the default offset date may 
	/// be the previous month for example.
	/// 
	/// The web part is connection provider that may be connected to multiple connection
	/// consumer web parts. The original intent was for this control to serve as a date filter
	/// to one or more Report Viewer web parts on the same page.
	/// </summary>
	/// <author>Seth Hildebrand</author>
	[ToolboxItemAttribute(false)]
	public class MonthFilter : System.Web.UI.WebControls.WebParts.WebPart, IWebEditable, ITransformableFilterValues
	{
		#region ------ DECLARATIONS ------

		/// <summary>
		/// The selected date that will be displayed in the dropdown list box. This value
		/// must be set early so that it is available when/if it must be provided to a 
		/// data consumer set up through a webpart connection.
		/// </summary>
		private DateTime _selectedDate = Convert.ToDateTime(DateTime.Today.ToString("MMM yyyy"));

		/// <summary>
		/// References the container div whose children are the controls that 
		/// make up the body of the web part.
		/// </summary>
		internal HtmlGenericControl _div;

		/// <summary>
		/// The style applied to the div container that holds the UI controls for this web part.
		/// </summary>
		private string _divStyle;

		/// <summary>
		/// References the span used to hold the label that precedes the dropdown list box.
		/// </summary>
		internal HtmlGenericControl _span;

		/// <summary>
		/// The style applied to the span that holds the UI label text controls for this web part.
		/// </summary>
		private string _spanStyle;

		/// <summary>
		/// References the dropdown list control.
		/// </summary>
		internal DropDownList _list;

		/// <summary>
		/// The style applied to the list that holds the dropdown list controls for this web part.
		/// </summary>
		private string _listStyle;

		//Default Constants
		const string DIV_STYLE = "padding:5px 3px 0px;font-weight:bold;";
		const string SPAN_STYLE = "";
		const string LIST_STYLE = "";
		const string LABEL_TEXT = "Select a date: ";
		const string DISPLAY_DATE_FORMAT = "MMM yyyy";
		const int START_OFFSET = 0;
		const int DEFAULT_OFFSET = -1;
		const int ADVANCE_DAYS = 31;
		const int NUMBER_MONTHS = 12;
		const string CONNECTION_PROVIDER_DATE_FORMAT = "MMM yyyy";
		const string URL_PARAM_NAME = "date";
		const string URL_DATE_FORMAT = "MMM yyyy";

		//Private Variables
		private string _labelText;
		private string _displayDateFormat;
		private int _startOffset;
		private int _defaultOffset;
		private int _advanceDays;
		private int _numberMonths;
		private string _connectionProviderDateFormat;
		private string _urlParamName;
		private string _urlDateFormat;

		#endregion

		#region ------ CONSTRUCTORS ------

		/// <summary>
		/// Default 'no parameter' constructor.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		public MonthFilter()
		{
			//Set default values;
			_divStyle = DIV_STYLE;
			_spanStyle = SPAN_STYLE;
			_listStyle = LIST_STYLE;
			_labelText = LABEL_TEXT;
			_displayDateFormat = DISPLAY_DATE_FORMAT;
			_startOffset = START_OFFSET;
			_defaultOffset = DEFAULT_OFFSET;
			_advanceDays = ADVANCE_DAYS;
			_numberMonths = NUMBER_MONTHS;
			_connectionProviderDateFormat = CONNECTION_PROVIDER_DATE_FORMAT;
			_urlParamName = URL_PARAM_NAME;
			_urlDateFormat = URL_DATE_FORMAT;
		}

		#endregion

		#region ------ PROPERTIES ------

		/// <summary>
		/// This public, shared property on the web part allows the label text that preceeds
		/// the dropdown list on the web part to be updateable through the web part editor.
		/// </summary>
		/// <example>
		/// Select a Date:
		/// </example>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(false),
		DefaultValueAttribute(LABEL_TEXT)]
		public string LabelText
		{
			get
			{
				return (_labelText.EndsWith(" ") ? _labelText : _labelText + " ");
			}
			set
			{
				_labelText = value;
			}
		}

		/// <summary>
		/// The style applied to the div container that holds the UI controls for this web part.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(true),
    WebDescription("Sets the style used with the div container that holds the UI controls on this web part."),
    WebDisplayName("Container Style"),
    Category("Advanced Filter"),
		DefaultValueAttribute(DIV_STYLE)]
		public string DivStyle
		{
			get
			{
				return _divStyle;
			}
			set
			{
				_divStyle = value;
			}
		}

		/// <summary>
		/// The style applied to the span label text UI control for this web part.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(true),
    WebDescription("Sets the style used with the label text (span) element."),
    WebDisplayName("Label Text Style"),
    Category("Advanced Filter"),
		DefaultValueAttribute(SPAN_STYLE)]
		public string SpanStyle
		{
			get
			{
				return _spanStyle;
			}
			set
			{
				_spanStyle = value;
			}
		}

		/// <summary>
		/// The style applied to the list UI controls for this web part.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(true),
    WebDescription("Sets the style used with the dropdown list box element."),
    WebDisplayName("List Style"),
    Category("Advanced Filter"),
		DefaultValueAttribute(LIST_STYLE)]
		public string ListStyle
		{
			get
			{
				return _listStyle;
			}
			set
			{
				_listStyle = value;
			}
		}

		/// <summary>
		/// This public, shared property on the web part allows the start offset to be
		/// updateable through the web part editor. The start offset calculates the first
		/// month listed in the dropdown in relation to the current month. This value may
		/// be a positive value to start in the future, zero to start with the current
		/// month, or negative to start with a month in the past.
		/// </summary>
		/// <remarks>
		/// The offset month is not necessarily the default month shown in the dropdown. The
		/// default month is controlled by the DefaultOffset property instead.
		/// </remarks>
		/// <example>
		/// 3, -1, 0, etc.
		/// </example>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(false),
    DefaultValueAttribute(START_OFFSET)]
		public int StartOffset
		{
			get
			{
				return _startOffset;
			}
			set
			{
				_startOffset = value;
			}
		}

		/// <summary>
		/// This public, shared property on the web part allows the default offset to be
		/// updateable through the web part editor. The default offset calculates the initial
		/// month shown in the dropdown in relation to the current month. This value may
		/// be positive to default to a month in the future, zero to always default to the current
		/// month, or negative to default to a month in the past.
		/// </summary>
		/// <remarks>
		/// The default month is not necessarily the same as the first month listed in the dropdown
		/// list. There first month in the list is controlled through the StartOffset property.
		/// </remarks>
		/// <example>
		/// 3, -1, 0, etc.
		/// </example>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(false),
    DefaultValueAttribute(DEFAULT_OFFSET)]
		public int DefaultOffset
		{
			get
			{
				return _defaultOffset;
			}
			set
			{
				_defaultOffset = value;
			}
		}

		/// <summary>
		/// May indicate that the default and start months should be advanced to the next month early after
		/// the given number of days within the current month have expired. The default is 31 so advancing
		/// would occur normally in this case. Setting a value of 20 days would mean that after the 20th day
		/// of the month, the default and start month should advance ahead on month early ahead of when it 
		/// would normally advance at the end of the current month.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(true),
    WebDescription("The default month and start month may be advanced (early) after a given number of days have elapsed in the current month."),
    WebDisplayName("Advance to next month after given number of days:"),
    Category("Advanced Filter"),
		DefaultValueAttribute(ADVANCE_DAYS)]
		public int AdvanceDays
		{
			get
			{
				return _advanceDays;
			}
			set
			{
				_advanceDays = value;
			}
		}

		/// <summary>
		/// This public, shared property on the web part allows the number of months listed
		/// in the web part to be updateable through the web part editor. 
		/// </summary>
		/// <example>
		/// 24, 12, 6, etc.
		/// </example>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(false),
   DefaultValueAttribute(NUMBER_MONTHS)]
		public int NumberOfMonthsToDisplay
		{
			get
			{
				return _numberMonths;
			}
			set
			{
				_numberMonths = value;
			}
		}

		/// <summary>
		/// Specifies the format that should be used when displaying the date in the 
		/// drop-down list box.
		/// </summary>
		/// <example>
		/// Use the same date format variables used in .Net. For example, MMM-dd-yyyy. The 
		/// default used in MMM yyyy.
		/// </example>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(false),
    DefaultValueAttribute(DISPLAY_DATE_FORMAT)]
		public string DisplayDateFormat
		{
			get
			{
				return _displayDateFormat;
			}
			set
			{
				_displayDateFormat = value;
			}
		}

		/// <summary>
		/// Specifies the format that should be used when the date value is provided through
		/// the date connection format or appended to the URL.
		/// </summary>
		/// <example>
		/// Use the same date format variables used in .Net. For example, MMM-dd-yyyy. The 
		/// default used in MMM yyyy.
		/// </example>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(false),
    DefaultValueAttribute(CONNECTION_PROVIDER_DATE_FORMAT)]
		public string ConnectionProviderDateFormat
		{
			get
			{
				return _connectionProviderDateFormat;
			}
			set
			{
				_connectionProviderDateFormat = value;
			}
		}

		/// <summary>
		/// The name of the parameter in the querystring to use to set the default date in the dropdown list. If the
    /// param name is not found in the querystring this rule will be ignored. Also, the default is only set when
    /// the page initially loads, it will not reset the date after a page postback. This is the same way that
    /// the OTB filter web parts work as well.
		/// </summary>
		/// <example>
		/// Use the same date format variables used in .Net. For example, MMM-dd-yyyy. The 
		/// default used in MMM yyyy.
		/// </example>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(true),
    WebDescription("The name of the parameter in the querystring used to set the initial default date."),
    WebDisplayName("Default QueryString Parameter Name"),
    Category("Advanced Filter"),
		DefaultValueAttribute(URL_PARAM_NAME)]
		public string UrlParamName
		{
			get
			{
				return _urlParamName;
			}
			set
			{
				_urlParamName = value;
			}
		}

		/// <summary>
		/// Specifies the format that should be used when parsing the date parameter from the querystring when
    /// setting the default date value. See the UrlParamName property for more information on this feature.
		/// </summary>
		/// <example>
		/// Use the same date format variables used in .Net For example, MMM-dd-yyyy. The 
		/// default used in MMM yyyy.
		/// </example>
		/// <author>Seth Hildebrand</author>
		[Personalizable(PersonalizationScope.Shared),
		WebBrowsable(true),
    WebDescription("The date format expected in the QueryString for the default date parameter."),
    WebDisplayName("Default QueryString Date Format"),
    Category("Advanced Filter"),
		DefaultValueAttribute(URL_DATE_FORMAT)]
		public string UrlDateFormat
		{
			get
			{
				return _urlDateFormat;
			}
			set
			{
				_urlDateFormat = value;
			}
		}

		/// <summary>
		/// This property is part of the ITransformableFilterValues interface. Indicates
		/// that all values are allowed from the filter.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		public bool AllowAllValue
		{
			get { return true; }
		}

		/// <summary>
		/// This property is part of the ITransformableFilterValues interface. Indicates
		/// that the filter value provided cannot be an empty value.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		public bool AllowEmptyValue
		{
			get { return false; }
		}

		/// <summary>
		/// This property is part of the ITransformableFilterValues interface. Indicates
		/// that the filter value provided cannot contain multiple values. In this case
		/// the value will be a single 'month year' string.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		public bool AllowMultipleValues
		{
			get { return false; }
		}

		/// <summary>
		/// This property is part of the ITransformableFilterValues interface.
		/// Represents the name of the parameter used when connecting the web part
		/// </summary>
		/// <author>Seth Hildebrand</author>
		public string ParameterName
		{
			get { return "Date"; }
		}

		/// <summary>
		/// This property is part of the ITransformableFilterValues interface. This
		/// returns the parameter values selected in the filter. Despite the return
		/// signature that indicates a collection of values, only one value will be
		/// included in the collection itself.
		/// </summary>
		/// <remarks>
		/// Notice that I am calling EnsureChildControls to make sure that the dropdown
		/// list has been created and that a selected date value is present.
		/// </remarks>
		/// <author>Seth Hildebrand</author>
		public System.Collections.ObjectModel.ReadOnlyCollection<string> ParameterValues
		{
			get
			{
				EnsureChildControls();
				List<string> paramValues = new List<string>();
				paramValues.Add(_selectedDate.ToString(ConnectionProviderDateFormat));
				return new System.Collections.ObjectModel.ReadOnlyCollection<string>(paramValues);
			}
		}

		#endregion

		#region ----- METHODS -----

		/// <summary>
		/// The logic in OnLoad sets the default selected date for the page. This happens within OnLoad so that any web part
		/// connection consumers may access the selected date value which would not otherwise be populated until the
		/// child controls have been created.
		/// </summary>
		/// <param name="e">Event arguments</param>
		/// <author>Seth Hildebrand</author>
		protected override void OnLoad(EventArgs e)
		{
			try
			{
				//Declarations
				int advanceDaysIncrement = 0;

				//Call base method.
				base.OnLoad(e);

				//When the page is not a postback, then the date in the dropdown list box must
				//be set to a default value. This can be taken from a querystring parameter, or
				//if a querystring parameter is not found then from the offset rules declared 
				//in the webpart properties.
				if (!Page.IsPostBack || _list == null)
				{
					//Set the default based on the date querystring param if one is found.
					if (this.Page.Request.QueryString[_urlParamName] != null)
					{
						try
						{
							//Attempt to do a ParseExact first, if this fails then try a standard parse.
							try
							{
								_selectedDate = DateTime.ParseExact(this.Page.Request.QueryString[_urlParamName].ToString(), "MMM yyyy", System.Globalization.CultureInfo.InvariantCulture);
							}
							catch (FormatException)
							{
								_selectedDate = DateTime.Parse(this.Page.Request.QueryString[_urlParamName].ToString());
							}
						}
						catch (Exception)
						{
							throw new FormatException("A parameter was found in the QuerySring to set the default value, however, the date format does not match the date format declared in the web part properties.");
						}
					}

					//Set the default based on the default offset rules declared in the web part properties.
					else
					{
						//Determine if the current day of the month has exceeded the advance days. If so, then the start and default
						//offsets should be incremented.
						if (DateTime.Today.Day > AdvanceDays)
						{
							advanceDaysIncrement = 1;
						}

						//Calculate the default month offset.
						_selectedDate = Convert.ToDateTime(DateTime.Today.ToString("MMM yyyy")).AddMonths(this.DefaultOffset + advanceDaysIncrement);
					}
				}

				//When the page IS a postback, the dropdown list box should be loaded from viewstate.
				//In this case, we need to set the _selectedDate variable equal to the value that is
				//found in the dropdown list.
				else
				{
					_selectedDate = Convert.ToDateTime(_list.SelectedValue);
				}
			}
			catch (Exception e1)
			{
				this.Controls.Add(new LiteralControl("<div style='color:red; word-wrap: break-word'>An error has occurred while trying to render the web part: " + e1.Message + "." + (e1.InnerException != null ? " " + e1.InnerException.Message + "." : "") + "</div>"));
			}
		}

		/// <summary>
		/// This method will create child controls for the web part and add them to the web part's
		/// control list prior to actually rendering the web part. Here we create a div element
		/// which in turn holds a span element for the label text, and the actual dropdown list
		/// control.
		/// 
		/// Note that each control is assigned both an ID and a class name which can be leveraged
		/// by SharePoint designers to affect the styling of the web part. This particular web
		/// part does not make use of any SharePoint styles or external styles. The class names are provided
		/// simply appended to provide the opportunity for styling.
		/// </summary>
		/// <remarks>
		/// Some of the cosmetic properties of the child controls are not applied until the Render methods.
		/// This is necessary so that changes made in the web part properties page get applied.
		/// </remarks>
		/// <author>Seth Hildebrand</author>
		protected override void CreateChildControls()
		{
			try
			{
				//Call base method.
				base.CreateChildControls();

				//Create UI controls and add them to the web part.
				_div = new HtmlGenericControl("div");
				this.Controls.Add(_div);
				_div.ID = "monthFilter_div";
				_div.Attributes.Add("class", "monthFilter_div");

				_span = new HtmlGenericControl("span");
				_div.Controls.Add(_span);
				_span.ID = "monthFilter_span";
				_span.Attributes.Add("class", "monthFilter_span");

				_list = new DropDownList();
				_div.Controls.Add(_list);
				_list.ID = "monthFilter_select";
				_list.Attributes.Add("class", "monthFilter_select");
				_list.SelectedIndexChanged += new EventHandler(_list_SelectedIndexChanged);
				_list.AutoPostBack = true;


				//Load items into the dropdown list box.
				if (!Page.IsPostBack || _list.Items.Count <= 0) LoadListBox();
			}
			catch (Exception e1)
			{
				this.Controls.Add(new LiteralControl("<div style='color:red; word-wrap: break-word'>An error has occurred while trying to render the web part: " + e1.Message + "." + (e1.InnerException != null ? " " + e1.InnerException.Message + "." : "") + "</div>"));
			}
		}

		/// <summary>
		/// Set the _selectedValue variable so that it may be used to set the UI as well as
		/// provide the selected value to any webpart connections.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		/// <author>Seth Hildebrand</author>
		void _list_SelectedIndexChanged(object sender, EventArgs e)
		{
			try
			{
				_selectedDate = Convert.ToDateTime(_list.SelectedValue);
			}
			catch (Exception e1)
			{
				this.Controls.Add(new LiteralControl("<div style='color:red; word-wrap: break-word'>An error has occurred while trying to render the web part: " + e1.Message + "." + (e1.InnerException != null ? " " + e1.InnerException.Message + "." : "") + "</div>"));
			}
		}

		/// <summary>
		/// Pre-render is used to apply cosmetic changes to the web part child controls after the web part properties page has
		/// been given a chance to apply its changes.
		/// </summary>
		/// <param name="e"></param>
		/// <author>Seth Hildebrand</author>
		protected override void OnPreRender(EventArgs e)
		{
			try
			{
				//Call base method.
				base.OnPreRender(e);

				//Ensure that all child controls have been created.
				EnsureChildControls();

				//Set label text.
				_span.InnerHtml = LabelText;
				_div.Style.Value = _divStyle;
				_span.Style.Value = _spanStyle;
				_list.Style.Value = _listStyle;

			}
			catch (Exception e1)
			{
				this.Controls.Add(new LiteralControl("<div style='color:red; word-wrap: break-word'>An error has occurred while trying to render the web part: " + e1.Message + "." + (e1.InnerException != null ? " " + e1.InnerException.Message + "." : "") + "</div>"));
			}
		}

		/// <summary>
		/// Provides the logic for loading the month/year dropdown values into the list box. This
		/// method uses the properties provided by the user through the web part editor to determine
		/// which months should be added to the list.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		public void LoadListBox()
		{
			//Declarations
			DateTime basePointer;
			DateTime datePointer;
			int advanceDaysIncrement = 0;

			try
			{
				//Clear list items.
				_list.Items.Clear();

				//Set base date.
				basePointer = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);

				//Determine if the current day of the month has exceeded the advance days. If so, then the start and default
				//offsets should be incremented.
				if (DateTime.Today.Day > AdvanceDays)
				{
					advanceDaysIncrement = 1;
				}

				//Load month items into list.			
				datePointer = basePointer.AddMonths(this.StartOffset + advanceDaysIncrement);
				for (int index = 0; index < this.NumberOfMonthsToDisplay; index++)
				{
					_list.Items.Add(new ListItem(datePointer.ToString(DisplayDateFormat), datePointer.ToShortDateString()));
					datePointer = datePointer.AddMonths(-1);
				}

				//Set the default value.
				_list.SelectedValue = _selectedDate.ToShortDateString();
			}
			catch (Exception e1)
			{
				this.Controls.Add(new LiteralControl("<div style='color:red; word-wrap: break-word'>An error has occurred while trying to render the web part: " + e1.Message + "." + (e1.InnerException != null ? " " + e1.InnerException.Message + "." : "") + "</div>"));
			}
		}

		/// <summary>
		/// Overridden to give the control an opportunity to trap and report rendering errors on the UI. In addition, version information
		/// is printed to the UI when the web part is in edit mode.
		/// </summary>
		/// <param name="writer"></param>
		/// <author>Seth Hildebrand</author>
		public override void RenderControl(HtmlTextWriter writer)
		{
			try
			{
				base.RenderControl(writer);

				//Display the version when in edit mode.
				if (this.WebPartManager.DisplayMode.AllowPageDesign)
				{
					Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
					writer.Write(
							"<div style='font-size:8pt; margin-top:20px; color:grey'>" +
							"Version: {0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision +
							"</div>");
				}
			}
			catch (Exception e1)
			{
				writer.Write("<div style='color:red; word-wrap: break-word'>An error has occurred while trying to render the web part: " + e1.Message + "." + (e1.InnerException != null ? " " + e1.InnerException.Message + "." : "") + "</div>");
			}
		}

		/// <summary>
		/// This method is overridden so that the custom web part editor (i.e. configuration panel) 
		/// is used when editing this web part rather than the default (i.e. generic pane) web part editor.
		/// </summary>
		/// <author>Seth Hildebrand</author>
		public override EditorPartCollection CreateEditorParts()
		{
			//Declarations
			List<EditorPart> editorParts;
			EditorPart editorPart;
			EditorPartCollection baseParts;

			//Create base editor part collection which we'll use as a return.
      editorParts = new List<EditorPart>();
			baseParts = base.CreateEditorParts();
      
      //Add the filter editor.
			editorPart = new MonthFilterEditor();
      editorParts.Add(editorPart);
			editorPart.ID = this.ID + "_monthFilterEditor";
      
      //Return editor collection.
			return new EditorPartCollection(baseParts, editorParts);
		}

    /// <summary>
    /// Provides this object as the connection source.
    /// </summary>
    /// <returns>An instance of this object.</returns>
		[ConnectionProvider("Date", "MonthFilterDateConnection", AllowsMultipleConnections = true)]
		public ITransformableFilterValues SetConnection()
		{
			return this;
		}

		#endregion

	}//End Class
}//End Namespace

